#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import requests
import time
import random
import string
import json
import os
import logging
import socket
import webbrowser
import sys
from dotenv import load_dotenv, set_key
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry


class TempMailManager:
    """
    临时邮箱管理器
    用于自动获取、管理临时邮箱和更新配置文件
    """
    
    def __init__(self, env_file=".env", max_retries=5, proxies=None):
        """
        初始化临时邮箱管理器
        
        参数:
            env_file: 环境变量文件路径
            max_retries: 最大重试次数
            proxies: 代理设置，如 {"http": "http://127.0.0.1:7890", "https": "http://127.0.0.1:7890"}
        """
        self.env_file = env_file
        self.session = self._create_session(max_retries, proxies)
        # 支持的临时邮箱域名
        self.available_domains = [
            "mailto.plus", 
            "fexpost.com", 
            "fexbox.org", 
            "mailbox.in.ua", 
            "rover.info", 
            "chitthi.in", 
            "fextemp.com", 
            "any.pink", 
            "merepost.com"
        ]
        
        # 确保.env文件存在
        if not os.path.exists(self.env_file):
            with open(self.env_file, "w") as f:
                f.write("# TempMail配置\n")
                f.write("DOMAIN=cursor.sh\n")
    
    def _create_session(self, max_retries=5, proxies=None):
        """创建网络会话，支持重试和代理"""
        session = requests.Session()
        
        # 设置请求头
        session.headers.update({
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
            "Accept": "application/json, text/plain, */*",
            "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
            "Origin": "https://tempmail.plus",
            "Referer": "https://tempmail.plus/"
        })
        
        # 配置自动重试
        retry = Retry(
            total=max_retries,
            connect=3,
            read=3,
            backoff_factor=1,
            status_forcelist=[429, 500, 502, 503, 504],
            respect_retry_after_header=True,
        )
        adapter = HTTPAdapter(max_retries=retry)
        session.mount("http://", adapter)
        session.mount("https://", adapter)
        
        # 设置代理
        if proxies:
            session.proxies.update(proxies)
            logging.info(f"使用代理: {proxies}")
        
        return session
    
    def _generate_pin(self, length=8):
        """生成随机PIN码"""
        return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
    
    def _generate_random_name(self, length=8):
        """生成随机邮箱用户名"""
        return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
    
    def create_new_mailbox(self, retry_count=0, max_retries=3):
        """
        创建新的临时邮箱
        
        参数:
            retry_count: 当前重试次数
            max_retries: 最大重试次数
            
        返回:
            dict: 包含邮箱信息的字典
        """
        # 防止无限递归
        if retry_count >= max_retries:
            logging.error(f"创建临时邮箱失败，超过最大重试次数 {max_retries}")
            # 提示用户手动获取邮箱
            return self._create_manual_mailbox()
            
        # 检查DNS解析是否正常
        if not self._check_dns("tempmail.plus"):
            logging.error("无法解析tempmail.plus域名，可能是网络问题或DNS配置问题")
            # 尝试换一个备用域名
            if not self._check_dns("mail.tm"):
                logging.error("备用域名mail.tm也无法解析，网络连接似乎存在问题")
                return self._create_manual_mailbox()
            else:
                logging.info("尝试使用备用邮箱服务mail.tm")
                # 这里可以添加使用mail.tm的逻辑，但目前先用手动方式
                return self._create_manual_mailbox()
        
        # 随机选择一个域名
        domain = random.choice(self.available_domains)
        # 生成随机用户名
        username = self._generate_random_name()
        # 生成PIN码
        pin = self._generate_pin()
        
        try:
            # 测试连接
            if not self._test_connection():
                logging.error("无法连接到tempmail.plus服务")
                return self._create_manual_mailbox()
            
            # 设置PIN码
            set_pin_url = f"https://tempmail.plus/api/set_pin?pin={pin}"
            set_pin_response = self.session.get(set_pin_url, timeout=15)
            
            if set_pin_response.status_code != 200:
                logging.error(f"设置PIN码失败: HTTP {set_pin_response.status_code}")
                time.sleep(2)
                return self.create_new_mailbox(retry_count + 1, max_retries)
            
            # 获取epin值
            cookies = self.session.cookies.get_dict()
            epin = cookies.get('epin', '')
            
            if not epin:
                logging.error("未能获取epin值")
                time.sleep(2)
                return self.create_new_mailbox(retry_count + 1, max_retries)
            
            # 获取新邮箱
            change_email_url = f"https://tempmail.plus/api/change?email={username}@{domain}&epin={epin}"
            change_email_response = self.session.get(change_email_url, timeout=15)
            
            if change_email_response.status_code != 200:
                logging.error(f"创建邮箱失败: HTTP {change_email_response.status_code}")
                time.sleep(2)
                return self.create_new_mailbox(retry_count + 1, max_retries)
            
            # 验证邮箱可用性
            verify_url = f"https://tempmail.plus/api/mails?email={username}@{domain}&limit=1&epin={epin}"
            verify_response = self.session.get(verify_url, timeout=15)
            
            if verify_response.status_code != 200:
                logging.warning(f"邮箱可用性验证失败，尝试继续使用: HTTP {verify_response.status_code}")
            
            # 邮箱信息
            mailbox_info = {
                "email": f"{username}@{domain}",
                "username": username,
                "domain": f"@{domain}",
                "epin": epin,
                "pin": pin
            }
            
            logging.info(f"成功创建临时邮箱: {mailbox_info['email']}")
            return mailbox_info
            
        except requests.exceptions.RequestException as e:
            logging.error(f"网络请求错误: {str(e)}")
            time.sleep(5)  # 网络错误后等待更长时间
            
            # 如果是连接错误，建议检查网络或使用代理
            if isinstance(e, requests.exceptions.ConnectionError):
                logging.error("连接错误，请检查网络连接或配置代理")
                
            return self.create_new_mailbox(retry_count + 1, max_retries)
        except Exception as e:
            logging.error(f"创建临时邮箱时出错: {str(e)}")
            time.sleep(2)
            return self.create_new_mailbox(retry_count + 1, max_retries)
    
    def _check_dns(self, domain):
        """检查域名是否可以解析"""
        try:
            socket.gethostbyname(domain)
            return True
        except socket.gaierror:
            return False
    
    def _test_connection(self, timeout=10):
        """
        测试与tempmail.plus的连接
        
        返回:
            bool: 连接是否成功
        """
        try:
            # 使用网站主页而不是 /api/ping，因为该API可能不存在
            response = self.session.get("https://tempmail.plus/", timeout=timeout)
            if response.status_code != 200:
                logging.warning(f"tempmail.plus 连接测试异常: HTTP {response.status_code}")
                return False
            return True
        except requests.exceptions.RequestException as e:
            logging.warning(f"tempmail.plus 连接测试失败: {str(e)}")
            return False
    
    def _create_manual_mailbox(self):
        """
        当自动创建失败时，提示用户手动获取临时邮箱信息
        
        返回:
            dict: 包含邮箱信息的字典，或None表示用户取消
        """
        logging.info("自动获取临时邮箱失败，尝试手动获取...")
        
        try:
            # 尝试打开浏览器访问tempmail.plus
            webbrowser.open("https://tempmail.plus/")
        except Exception:
            pass
        
        print("\n" + "="*60)
        print("自动获取临时邮箱失败，请按以下步骤手动获取:")
        print("1. 访问 https://tempmail.plus/")
        print("2. 设置PIN码 (点击网页右上角的Settings然后设置PIN)")
        print("3. 获取邮箱信息并在下方输入")
        print("="*60 + "\n")
        
        email = input("请输入临时邮箱地址 (例如: abcde@mailto.plus): ").strip()
        if not email or "@" not in email:
            logging.error("邮箱格式不正确")
            return None
        
        username, domain = email.split("@", 1)
        domain = "@" + domain
        
        pin = input("请输入PIN码: ").strip()
        if not pin:
            logging.error("PIN码不能为空")
            return None
        
        epin = input("请输入epin值 (在浏览器Cookie中或地址栏参数中): ").strip()
        if not epin:
            logging.warning("未提供epin值，将使用PIN码代替")
            epin = pin
        
        mailbox_info = {
            "email": email,
            "username": username,
            "domain": domain,
            "epin": epin,
            "pin": pin,
            "manual": True
        }
        
        logging.info(f"已手动设置临时邮箱: {email}")
        return mailbox_info
    
    def update_env_file(self, mailbox_info):
        """
        更新.env文件中的邮箱配置
        
        参数:
            mailbox_info: 邮箱信息字典
        
        返回:
            bool: 是否成功更新
        """
        try:
            # 确保.env文件存在
            if not os.path.exists(self.env_file):
                with open(self.env_file, "w") as f:
                    f.write("# TempMail配置\n")
                    f.write("DOMAIN=cursor.sh\n")
                    
            # 加载当前.env文件
            load_dotenv(self.env_file)
            
            # 读取文件内容
            try:
                with open(self.env_file, "r", encoding="utf-8") as f:
                    env_content = f.read()
            except UnicodeDecodeError:
                # 尝试其他编码
                with open(self.env_file, "r", encoding="latin-1") as f:
                    env_content = f.read()
            
            # 更新或添加TEMP_MAIL
            if "TEMP_MAIL=" in env_content:
                env_content = self._replace_env_var(env_content, "TEMP_MAIL", mailbox_info["username"])
            else:
                env_content += f"\nTEMP_MAIL={mailbox_info['username']}\n"
            
            # 更新或添加TEMP_MAIL_EPIN
            if "TEMP_MAIL_EPIN=" in env_content:
                env_content = self._replace_env_var(env_content, "TEMP_MAIL_EPIN", mailbox_info["epin"])
            else:
                env_content += f"TEMP_MAIL_EPIN={mailbox_info['epin']}\n"
                
            # 更新或添加TEMP_MAIL_EXT
            if "TEMP_MAIL_EXT=" in env_content:
                env_content = self._replace_env_var(env_content, "TEMP_MAIL_EXT", mailbox_info["domain"])
            else:
                env_content += f"TEMP_MAIL_EXT={mailbox_info['domain']}\n"
            
            # 确保DOMAIN存在
            if "DOMAIN=" not in env_content:
                env_content += f"DOMAIN=cursor.sh\n"
                
            # 写回文件
            with open(self.env_file, "w", encoding="utf-8") as f:
                f.write(env_content)
                
            logging.info(f"已更新.env文件: {mailbox_info['email']}")
            return True
        except Exception as e:
            logging.error(f"更新.env文件时出错: {str(e)}")
            return False
    
    def _replace_env_var(self, content, var_name, new_value):
        """替换环境变量值"""
        import re
        pattern = f"{var_name}=.*"
        replacement = f"{var_name}={new_value}"
        return re.sub(pattern, replacement, content)
    
    def check_mailbox_available(self, email, epin, timeout=15):
        """
        检查临时邮箱是否可用
        
        参数:
            email: 完整邮箱地址
            epin: 邮箱的epin值
            timeout: 超时时间（秒）
            
        返回:
            bool: 邮箱是否可用
        """
        try:
            url = f"https://tempmail.plus/api/mails?email={email}&limit=1&epin={epin}"
            response = self.session.get(url, timeout=timeout)
            return response.status_code == 200
        except Exception as e:
            logging.error(f"检查邮箱可用性时出错: {str(e)}")
            return False


def load_proxies_from_env():
    """从环境变量加载代理设置"""
    try:
        load_dotenv()
        http_proxy = os.getenv("HTTP_PROXY")
        https_proxy = os.getenv("HTTPS_PROXY")
        
        proxies = {}
        if http_proxy:
            proxies["http"] = http_proxy
        if https_proxy:
            proxies["https"] = https_proxy
            
        if proxies:
            logging.info(f"已加载代理设置: {proxies}")
            return proxies
        return None
    except Exception as e:
        logging.warning(f"加载代理设置时出错: {str(e)}")
        return None


def setup_logging():
    """配置日志"""
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s - %(levelname)s: %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S"
    )


def manual_check_connection():
    """检查连接，提供诊断信息"""
    logging.info("开始连接检查...")
    
    # 检查DNS
    domains = ["tempmail.plus", "mail.tm", "google.com"]
    print("\n--- DNS检查 ---")
    for domain in domains:
        try:
            ip = socket.gethostbyname(domain)
            print(f"✅ {domain} 解析成功: {ip}")
        except socket.gaierror:
            print(f"❌ {domain} 解析失败")
    
    # 检查HTTP连接
    print("\n--- HTTP连接检查 ---")
    urls = [
        "https://tempmail.plus/",
        "https://mail.tm/",
        "https://www.google.com/"
    ]
    
    session = requests.Session()
    for url in urls:
        try:
            response = session.get(url, timeout=10)
            print(f"✅ {url} 连接成功: HTTP {response.status_code}")
        except Exception as e:
            print(f"❌ {url} 连接失败: {str(e)}")
    
    # 检查代理设置
    print("\n--- 代理设置检查 ---")
    proxies = load_proxies_from_env()
    if proxies:
        print(f"✅ 已配置代理: {proxies}")
        
        # 测试使用代理连接
        try:
            proxy_session = requests.Session()
            proxy_session.proxies.update(proxies)
            response = proxy_session.get("https://tempmail.plus/", timeout=10)
            print(f"✅ 使用代理连接tempmail.plus成功: HTTP {response.status_code}")
        except Exception as e:
            print(f"❌ 使用代理连接失败: {str(e)}")
    else:
        print("❌ 未配置代理")
        print("建议: 如果直接连接失败，请在.env文件中配置HTTP_PROXY和HTTPS_PROXY")
    
    print("\n如果DNS解析和连接测试均失败，可能是网络问题，建议：")
    print("1. 检查网络连接")
    print("2. 配置代理服务器")
    print("3. 使用手动模式获取临时邮箱")
    print()


if __name__ == "__main__":
    setup_logging()
    
    import argparse
    parser = argparse.ArgumentParser(description="临时邮箱管理工具")
    parser.add_argument("--check", action="store_true", help="检查连接状态")
    parser.add_argument("--manual", action="store_true", help="使用手动模式获取邮箱")
    args = parser.parse_args()
    
    if args.check:
        manual_check_connection()
        sys.exit(0)
    
    proxies = load_proxies_from_env()
    manager = TempMailManager(proxies=proxies)
    
    if args.manual:
        mailbox = manager._create_manual_mailbox()
    else:
        mailbox = manager.create_new_mailbox()
        
    if mailbox:
        manager.update_env_file(mailbox)
        print(f"临时邮箱已创建并配置: {mailbox['email']}")
    else:
        print("创建临时邮箱失败") 